package ananly;

import oracle.xml.parser.v2.XMLDocument;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.crypto.Data;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/*
* 解析控制程序 
*/ 
public class SaxProcessor extends ConnectionProvider { 
  /*工作队列，暂存解析的数据*/ 
  private Vector workQueue = new Vector();

  /*线程池,源作者用Hashtable实现的线程池，我觉得JDK1.5已经有现成的了，何必再造轮子呢*/ 
  BlockingDeque<Runnable> queue = new LinkedBlockingDeque<Runnable>();
  ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1,
      TimeUnit.MINUTES, queue);
    
  private int threadCount; 
  Thread saxReader; 
  private boolean parserActive = false; 

  private void setWriterCount(int count) { 
    this.threadCount = count; 
  } 

  private int getWriterCount() { 
    return this.threadCount; 
  } 

    

  protected synchronized void setParserActive() { 
    this.parserActive = true; 
  } 

  protected synchronized void setParsingComplete() { 
    this.parserActive = false; 
    notifyAll(); 
  } 

  public synchronized boolean parsingComplete() { 
    return !this.parserActive; 
  } 

  public synchronized boolean processingComplete() { 

    boolean result = (parsingComplete()) && (this.workQueue.size() == 0); 
    return result; 
  } 

  private boolean listQueueFull() { 
    return (this.workQueue.size() >= (2 * getWriterCount())); 
  } 

  /* 向工作队列添加一个任务,并通知所有受阻线程 */ 
  protected synchronized void addToQueue(List data) throws SAXException {
    if (listQueueFull()) { 
      try { 
        wait(); 
      } catch (InterruptedException ie) { 
        ie.printStackTrace(); 
      } 
    } 
     
    this.workQueue.addElement(data); 
    notifyAll(); 
     
  } 

  public synchronized List getNextData(String thread) { 
    List data = null; 
    while (!parsingComplete() && (this.workQueue.size() == 0)) { 
      try { 
        wait(); 
      } catch (InterruptedException ioe) { 
      } 
    } 
    if (this.workQueue.size() > 0) { 
      data = (List) this.workQueue.remove(0); 
      notifyAll(); 
    } 
    return data; 
  } 

  public SaxProcessor() throws SQLException, IOException, SAXException {
    super(); 
  } 

  public void doSomething(String[] args) { 
    try { 
      setWriterCount(Integer.parseInt(getSetting("ThreadCount","4"))); 
      //获得要解析的文件
      this.saxReader = createSourceProcessor();
      this.setParserActive(); 
      this.saxReader.start(); 
      createDatabaseWriters(); 
      waitForCompletion(); 
    } catch (Exception e) { 
      e.printStackTrace(); 
      this.setParsingComplete(); 
    } 
  } 

  private synchronized void waitForCompletion() { 
    while (!parsingComplete()) { 
      try { 
        wait(); 
      } catch (InterruptedException ioe) { 
      } 
    } 
    this.executor.shutdown(); 
  } 

  private void createDatabaseWriters() throws SQLException { 
    DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance();
    df.applyPattern("000000"); 
    int commitCharge = Integer.parseInt(getSetting("CommitCharge", "50")); 
    for (int i = 0; i < getWriterCount(); i++) { 
      System.out.println(getWriterCount()); 
      String threadName = "Writer_" + df.format(i + 1); 
      Connection conn = getNewConnection();
      conn.setAutoCommit(false); 
      DatabaseWriter writer = new DatabaseWriter(this, threadName, conn); 
      writer.setParameters(commitCharge); 
        
      this.executor.execute(writer); 
    } 
  } 

  private Thread createSourceProcessor() throws SQLException { 
    String threadName = "SaxReader"; 
    SourceProcessor saxReader = new SourceProcessor(threadName); 
    saxReader.setSaxProcessor(this); 
     saxReader.setTargetFilename(getSetting("SourceXML","DIR")); 
    return saxReader; 
  } 

  protected synchronized void printXML(Document xml, PrintWriter pw)
      throws IOException { 
    ((XMLDocument) xml).print(pw);
  } 

        /*主函数*/ 
  public static void main(String[] args) {
      Date beginDate = new Date();
    try { 
      SaxProcessor app = new SaxProcessor(); 
      app.initializeConnection(); 
      app.doSomething(args);
        System.out.println(beginDate.getTime()-new Date().getTime());
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
  public Vector getWorkQueue() { 
    return workQueue; 
  } 

  public void setWorkQueue(Vector workQueue) { 
    this.workQueue = workQueue; 
  } 
} 